/*
 * CuerpoCangrejo.cpp
 *
 *  Created on: 30/09/2013
 *      Author: ezequiel
 */

#include "Esfera.h"

Esfera::Esfera(const float radius) {

this->sphere_vertex_buffer = new GLfloat();
this->sphere_index_buffer = new GLuint();
this->sphere_texture_buffer = new GLfloat();
this->camara = new Camara();
this->crearForma(radius, 32, 32);
}

Esfera::~Esfera() {
delete this->sphere_index_buffer;
delete this->sphere_vertex_buffer;
delete this->sphere_texture_buffer;
//delete this->camara; //si elimino este puntero me elimina la camara??
//delete this->vertex_buffer;
//delete this->index_buffer;
}

void Esfera::render(GLuint handle, glm::mat4* matModelo) {
    // Normal Matrix
//	glBindTexture (GL_TEXTURE_2D, this->textureid);
	this->renderMatrix(handle, &proyeccion);
    glm::mat3 normal_matrix = glm::mat3 ( 1.0f );
    glm::mat4* view_matrix = this->camara->getViewMatrix();
    glm::mat4 aux = (*view_matrix) * (*matModelo);	//TODO VER COMO METER LA VIEW_MATRIX
    for (int i=0; i<3; i++)
        for (int j=0; j<3; j++)
            normal_matrix[i][j] = aux[i][j];

    // Bind Normal MAtrix
    GLuint location_normal_matrix = glGetUniformLocation( handle, "NormalMatrix");
    if( location_normal_matrix >= 0 )
	{
        glUniformMatrix3fv( location_normal_matrix, 1, GL_FALSE, &normal_matrix[0][0]);
	}

    // Bind Model Matrix
    GLuint location_model_matrix = glGetUniformLocation( handle, "ModelMatrix");
    if( location_model_matrix >= 0 )
	{
		glUniformMatrix4fv( location_model_matrix, 1, GL_FALSE,&((*matModelo)[0][0]));
	}

    glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
//	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, sphere_vertex_buffer);
	glNormalPointer(GL_FLOAT, 0, sphere_vertex_buffer);
//	glTexCoordPointer(2, GL_FLOAT, 0, sphere_texture_buffer);
    glDrawElements(GL_TRIANGLE_STRIP, index_buffer.size(), GL_UNSIGNED_INT, sphere_index_buffer);
//    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    delete view_matrix;
}

void Esfera::render(GLuint handle) {
}

void Esfera::setCamara(Camara* cam) {
	this->camara  = cam ;
}

void Esfera::crearForma(const float radius, const unsigned int loops,
		const unsigned int segmentsPerLoop) {


    if (this->vertex_buffer.size() >0)
    {
        this->vertex_buffer.clear();
    }

    if (this->index_buffer.size() >0)
    {
        this->index_buffer.clear();
    }

//    if (this->texture_buffer.size() >0)
//    {
//        this->texture_buffer.clear();
//    }

    float PI = 3.1415f;

	for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
	{
		float theta = 0;
		float phi = loopSegmentNumber * 2 * PI / segmentsPerLoop;
		float sinTheta = std::sin(theta);
		float sinPhi = std::sin(phi);
		float cosTheta = std::cos(theta);
		float cosPhi = std::cos(phi);

        //
        this->vertex_buffer.push_back(radius * cosPhi * sinTheta); // Vx
        this->vertex_buffer.push_back(radius * sinPhi * sinTheta); // Vy
        this->vertex_buffer.push_back(radius * cosTheta);          // Vz
	}
	for (unsigned int loopNumber = 0; loopNumber <= loops; ++loopNumber)
	{
		for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
		{
			float theta = (loopNumber * PI / loops) + ((PI * loopSegmentNumber) / (segmentsPerLoop * loops));
			if (loopNumber == loops)
			{
				theta = PI;
			}
			float phi = loopSegmentNumber * 2 * PI / segmentsPerLoop;
			float sinTheta = std::sin(theta);
			float sinPhi = std::sin(phi);
			float cosTheta = std::cos(theta);
			float cosPhi = std::cos(phi);

            this->vertex_buffer.push_back(radius * cosPhi * sinTheta);
            this->vertex_buffer.push_back(radius * sinPhi * sinTheta);
            this->vertex_buffer.push_back(radius * cosTheta);
//            this->texture_buffer.push_back(pasoU);
//            this->texture_buffer.push_back(pasoV);
//            pasoU += 0.03125;

		}
	}
	for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
	{
		this->index_buffer.push_back(loopSegmentNumber);
		this->index_buffer.push_back(segmentsPerLoop + loopSegmentNumber);
	}
	for (unsigned int loopNumber = 0; loopNumber < loops; ++loopNumber)
	{
		for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
		{
			this->index_buffer.push_back(((loopNumber + 1) * segmentsPerLoop) + loopSegmentNumber);
			this->index_buffer.push_back(((loopNumber + 2) * segmentsPerLoop) + loopSegmentNumber);
		}
	}

    //
    if (this->sphere_vertex_buffer != NULL)
    {
        delete[] this->sphere_vertex_buffer;
    }
    this->sphere_vertex_buffer = new float[this->vertex_buffer.size()];

    if ( this->sphere_index_buffer != NULL)
    {
        delete[] this->sphere_index_buffer;
    }
    this->sphere_index_buffer = new unsigned int[this->index_buffer.size()];

    std::vector<float>::iterator vertex_it;
    unsigned int v = 0;
    for (vertex_it = this->vertex_buffer.begin(); vertex_it != this->vertex_buffer.end(); vertex_it++)
    {
        this->sphere_vertex_buffer[v] = *vertex_it;
        v++;
    }

    std::vector<unsigned int>::iterator index_it;
    unsigned int i = 0;
    for (index_it = this->index_buffer.begin(); index_it != this->index_buffer.end(); index_it++)
    {
        this->sphere_index_buffer[i] = *index_it;
        i++;
    }

//    std::vector<float>::iterator texture_it;
//    i = 0;
//    for (texture_it = this->texture_buffer.begin(); texture_it != this->texture_buffer.end(); texture_it++)
//    {
//        this->sphere_texture_buffer[i] = *texture_it;
//        i++;
//    }

}


